package com.ts.api.module.distribute.service.impl;

import com.gitee.apanlh.util.base.CollUtils;
import com.ts.api.common.redis.DistributeRedisKey;
import com.ts.api.common.util.RedisCache;
import com.ts.api.module.distribute.dao.DistributeDao;
import com.ts.api.module.distribute.entity.DistributeLinkPO;
import com.ts.api.module.distribute.entity.bo.DistributeLinkBO;
import com.ts.api.module.distribute.service.DistributePvService;
import com.ts.api.module.distribute.service.DistributeService;
import com.ts.api.module.distribute.service.DistributeUvService;
import eu.bitwalker.useragentutils.UserAgent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 *  分配代理链接
 */
@Service
public class DistributeServiceImpl implements DistributeService {

    @Autowired
    private DistributeUvService distributeUvService;
    @Autowired
    private DistributePvService distributePvService;
    @Autowired
    private DistributeDao distributeDao;
    @Autowired
    private RedisCache redisCache;

    @Override
    public List<DistributeLinkPO> list(String uniqueCode) {
        return distributeDao.list(uniqueCode);
    }

    @Override
    public List<DistributeLinkBO> checkLinkAndModify(List<DistributeLinkPO> list) {
        Long groupId = CollUtils.findFirstNotNull(list, t -> t.getGroupId());
        String redisKey = DistributeRedisKey.getLinkKey(groupId);

        Boolean exist = redisCache.hasKey(redisKey);
        //  不存在则新增
        if (!exist) {
            List<DistributeLinkBO> listBO = DistributeLinkBO.create(list);
            redisCache.setCacheList(redisKey, listBO);
            return listBO;
        }

        //  获取缓存数据
        List<DistributeLinkBO> cacheList = redisCache.getCacheList(redisKey);
        //  存入新缓存的值
        List<DistributeLinkBO> setList = new ArrayList<>();

        //  缓存数据对比源数据，缓存数据存在则更新，缺少则丢弃(代表子链接已经被删除)
        for (int i = 0; i < cacheList.size(); i++) {
            DistributeLinkBO linkBO = cacheList.get(i);

            Optional<DistributeLinkPO> first = list.stream().filter(t -> t.getId().equals(linkBO.getId())).findFirst();
            if (first.isPresent()) {
                //  更新实体
                DistributeLinkPO dbPO = first.get();
                linkBO.setLinkMaxClick(dbPO.getLinkMaxClick());
                linkBO.setUrl(dbPO.getUrl());
                linkBO.setStatus(dbPO.getStatus());
                linkBO.setGroupId(dbPO.getGroupId());
                linkBO.setId(dbPO.getId());
                setList.add(linkBO);
            }
        }

        //  检测是否存在新增子链接
        for (int i = 0; i < list.size(); i++) {
            DistributeLinkPO dbPO = list.get(i);

            Optional<DistributeLinkBO> first = setList.stream().filter(t -> t.getId().equals(dbPO.getId())).findFirst();
            if (!first.isPresent()) {
                DistributeLinkBO linkBO = new DistributeLinkBO();
                linkBO.setId(dbPO.getId());
                linkBO.setLinkMaxClick(dbPO.getLinkMaxClick());
                linkBO.setGroupId(dbPO.getGroupId());
                linkBO.setUrl(dbPO.getUrl());
                linkBO.setStatus(dbPO.getStatus());
                linkBO.setCount(0);
                setList.add(linkBO);
            }
        }

        //  删除原有值，返回新值
        redisCache.deleteObject(redisKey);
        redisCache.setCacheList(redisKey, setList);
        return setList;
    }

    @Override
    public DistributeLinkBO getDistributeLink(List<DistributeLinkPO> list, List<DistributeLinkBO> listBO) {
        Long groupId = CollUtils.findFirstNotNull(listBO, t -> t.getGroupId());
        String redisKey = DistributeRedisKey.getLinkKey(groupId);

        boolean allDisable = true;
        //  获取缓存链接
        for (int i = 0; i < listBO.size(); i++) {
            DistributeLinkBO link = listBO.get(i);
            Integer enableStatus = 1;
            if (enableStatus.equals(link.getStatus())) {
                allDisable = false;

                if (link.getCount() < link.getLinkMaxClick()) {
                    //  自增
                    link.increment();
                    redisCache.setCacheListSet(redisKey, i, link);
                    return link;
                }
            }
        }

        //  如果链接全被关闭，则直接不跳转
        if (allDisable) {
            //  只返回链接组
            DistributeLinkBO groupLinkBO = new DistributeLinkBO();
            groupLinkBO.setGroupId(groupId);
            return groupLinkBO;
        }

        //  链接次数都满了，将修改值重新创建
        redisCache.deleteObject(redisKey);
        //  根据原始List重新创建,避免数据为旧数据
        List<DistributeLinkBO> newlinkBOList = DistributeLinkBO.create(list);
        //  设置缓存时首个元素自增一次
        DistributeLinkBO newLinkBO = DistributeLinkBO.firstElementIncrement(newlinkBOList);
        redisCache.setCacheList(redisKey, newlinkBOList);
        return newLinkBO;
    }

    @Override
    public void insertGroupVisitor(String ip, UserAgent userAgent, DistributeLinkBO distributeLinkBO) {
        // pv
        distributePvService.insertGroupPv(ip, userAgent, distributeLinkBO.getGroupId());
        // uv
        try {
            distributeUvService.insertGroupUv(ip, userAgent, distributeLinkBO.getGroupId());
        } catch (DuplicateKeyException e) {
            // do nothing
        }
    }

    @Override
    public void insertLinkVisitor(String ip, UserAgent userAgent, DistributeLinkBO distributeLinkBO) {
        // pv
        distributePvService.insertLinkPv(ip, userAgent, distributeLinkBO);
        // uv
        try {
            distributeUvService.insertLinkUv(ip, userAgent, distributeLinkBO);
        } catch (DuplicateKeyException e) {
            // do nothing
        }
    }
}
